<!--
 * @Title:
 * @Descripttion:
 * @Version: 2.0
 * @Author: tangyong
 * @Date: 2025-04-08 13:48:15
 * @LastEditors: weidewei
 * @LastEditTime: 2025-07-02 15:36:08
-->
<template>
  <div class="comp-dynamic-table">
    <el-form ref="formInstance" :disabled="!canEdit" :model="formData" @submit.prevent>
      <table ref="tableRef" class="el-table-simple">
        <tbody>
          <tr v-for="(item, index) in tableRules" :key="index">
            <td
              v-for="(col, idx) in item"
              :key="idx"
              :colspan="col.colSpan"
              :rowspan="col.rowSpan"
              :style="getTdStyle(col.colObj)"
            >
              <el-form-item
                :prop="col.prop"
                :rules="getRule(col)"
              >
                <!-- 纯文本 -->
                <span
                  :style="getShowStyle(col.colObj)"
                  v-if="col.type === 'text'"
                  class="cell-span"
                >
                  <span>{{ col.value }}</span>
                  <el-tooltip
                    v-if="col.tipContent"
                    effect="dark"
                    :content="col.tipContent"
                    raw-content
                    placement="right"
                  >
                    <el-icon color="#E6A23C"><Opportunity /></el-icon>
                  </el-tooltip>
                </span>
                <!-- 输入框 -->
                <el-input
                  v-else
                  v-bind="getColumnProps(col)"
                  v-model="formData[col.prop]"
                  @click.stop
                />
              </el-form-item>
            </td>
          </tr>
        </tbody>
      </table>
    </el-form>
  </div>
</template>
<script lang="ts" setup>
  import { defineAsyncComponent } from "vue"
  import { isEmptyObj, isEmpty } from "@/utils/index";
  import { cloneDeep } from "lodash-es";
  import { Opportunity } from "@element-plus/icons-vue";
  // const DialogByFieldOperate = defineAsyncComponent(() => import("./DialogByFieldOperate.vue"));

  const props = defineProps({
    canEdit: {
      type: Boolean,
      default: true
    },
    rules: {
      type: Array,
      default: () => []
    },
    data: {
      type: Object,
      default: () => ({})
    }
  });

  const { proxy } = getCurrentInstance()!;

  const formInstance: any = shallowRef(null);
  const formData: any = ref({ ...props.data });
  const tableRules: any = shallowRef([]);
  const dialogStatus = ref(false);
  const componentName: any = shallowRef();
  const dialogData: any = shallowRef(null);
  const action: any = ref("");
  watch(
    () => props.rules,
    (arr) => {
      if (!Array.isArray(arr) || !arr.length) return;
      nextTick(() => {
        initRules();
      });
    },
    { immediate: true }
  );

  function initRules() {
    let originRules = cloneDeep(props.rules);
    console.log(originRules);
    const exposed: any = proxy?.$.exposed;
    originRules.forEach((item: any) => {
      item.on = {
        change: () => {
          nextTick(() => {
            dispatchEvent();
          });
        }
      };
      if (Array.isArray(item.validate) && item.validate.length) {
        item.validate.forEach((it) => {
          if (it.type === "fn") {
            it.validator =
              typeof exposed[it.validator] === "function" ? exposed[it.validator] : function () {};
          }
        });
      }
    });
    // const groupRules = originRules.reduce((acc: any, cur: any) => {
    //   if (cur.startRow) {
    //     acc.push([cur]);
    //   } else {
    //     acc[acc.length - 1].push(cur);
    //   }
    //   return acc;
    // }, []);
    const groupByRules = (dataArray) => {
      return dataArray.reduce((groups, item) => {
        const rowKey = item.colObj.cellRow; // 获取cellRow作为分组键
        if (!groups[rowKey]) {
          groups[rowKey] = [];
        }
        groups[rowKey].push(item);
        return groups;
      }, {});
    };
    const groupRules = groupByRules(originRules);
    tableRules.value = groupRules;
  }

  function getRule(col) {
    if (Array.isArray(col.validate) && col.validate.length) return col.validate;
    return [];
  }

  function getColumnProps(column) {
    return typeof column.props === "object" ? column.props : {};
  }

  function getColumnEvents(column) {
    if (isEmptyObj(column.on)) return {};
    const tempEvt = {};
    Object.keys(column.on).forEach((evtName) => {
      tempEvt[evtName] = column.on[evtName];
    });
    return tempEvt;
  }

  function dispatchEvent() {
    formInstance.value.clearValidate();
    props.rules.forEach((item: any) => {
      if (Array.isArray(item.emit) && item.emit.length) {
        item.emit.forEach((it) => {
          if (it.fnName === "excuteFormula") {
            excuteFormula(it.params, item.prop);
          }
        });
      }
    });
  }

  function excuteFormula(params, prop?) {
    if (isEmpty(params?.express)) return;
    const exp = params.express.replace(/{([^}]+)\}/g, (_a, b) => {
      return +formData.value[b] || 0;
    });
    try {
      const ret = eval(exp);
      if (!isEmpty(prop)) {
        formData.value[prop] = ret;
      }
      return ret;
    } catch (e) {
      console.log(e);
    }
  }

  // 比较相等
  function comppareEqual(rule, _val, cb) {
    const ret = excuteFormula(rule.params);
    if (ret == null || isEmpty(cb)) return cb();
    if (ret !== 0) {
      cb(new Error(rule.message));
    } else {
      cb();
    }
  }

  // 比较不等
  function compareUnequal(rule, _val, cb) {
    const ret = excuteFormula(rule.params);
    if (ret == null || isEmpty(cb)) return cb();
    if (ret === 0) {
      cb(new Error(rule.message));
    } else {
      cb();
    }
  }

  // 比较大于或等于
  function compareGreaterThanOrEqual(rule, _val, cb) {
    const ret = excuteFormula(rule.params);
    if (ret == null || isEmpty(cb)) return cb();
    if (ret < 0) {
      cb(new Error(rule.message));
    } else {
      cb();
    }
  }

  // 比较是否小于1
  function compareLessThanOne(rule, _val, cb) {
    const ret = excuteFormula(rule.params);
    if (ret == null || isEmpty(cb)) return cb();
    if (ret >= 1) {
      cb(new Error(rule.message));
    } else {
      cb();
    }
  }

  let selectedCol: any = null;

  function validate() {
    return new Promise((resolve) => {
      formInstance.value.validate((valid) => {
        if (valid) {
          resolve(cloneDeep(formData.value));
        } else {
          resolve(false);
        }
      });
    });
  }

  function handleDoubleClick(col) {
    if (isEmptyObj(col)) return;
    dialogStatus.value = true;
    componentName.value = DialogByFieldOperate;
    dialogData.value = col.colObj;
    action.value = "edit";
  }

  function getShowStyle(colObj) {
    try {
      return colObj.cellStyle ? JSON.parse(colObj.cellStyle) : {};
    } catch {
      return {};
    }
  }

  function getTdStyle(colObj) {
    return {
      width: colObj.colWidth || "150px",
      minWidth: colObj.colWidth || "150px",
      maxWidth: colObj.colWidth || "150px",
      height: colObj.rowHeight || "auto",
      minHeight: colObj.rowHeight || "auto",
      maxHeight: colObj.rowHeight || "auto"
    };
  }

  defineExpose({
    validate,
    excuteFormula,
    comppareEqual,
    compareUnequal,
    compareGreaterThanOrEqual,
    compareLessThanOne
  });
</script>

<style lang="scss" scoped>
  table {
    table-layout: auto;
  }
  .el-table-simple {
    tbody {
      border-top: 1px solid #e3e8ee;
    }

    :deep(.el-form-item) {
      margin-bottom: 0;

      .el-form-item__content {
        .cell-span {
          width: 100%;
          padding: 5px 0;
          line-height: 18px;
        }
      }
    }
  }
</style>
